﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using LGE;
using System.IO;

namespace UpUp
{
    public class BlockManager
    {
        PlayScreen ps;
        public Block[] block = new Block[2];
        List<Geiser>[] geiserList = new List<Geiser>[2];
        Flag flag = null;

        // Tile Codes
        const int spikeCode = 93;
        const int geiserCode = 94;
        const int crystalCode = 95;
        const int flagCode = 96;

        public BlockManager(PlayScreen ps)
        {
            this.ps = ps;
            Tile.UndergroundCode = 6;
            Block.checkCodeActions.Add(crystalCode, delegate(Block b, Point p) { ps.c.crystals++; ps.crystalsInThisSession++; b.map[1][p.Y][p.X] = 0; Audio.PlaySFX(ps.c.SFX_Crystal); });
            Block.checkCodeActions.Add(spikeCode, delegate(Block b, Point p) { ps.c.hp = 0; });
        }

        public void Load()
        {
            ps.level = 0;
            ps.crystalsInThisSession = 0;
            ps.HMaxInThisSession = 0;
            ps.finished = false;
            flag = null;
            geiserList[0] = new List<Geiser>();
            geiserList[1] = new List<Geiser>();
            block[0] = new Block(new Vector2(0, -1444.8f), "Content\\Blocks\\a.block");
            CheckSpecialTiles(0);
            CreateNextBlock();
        }

        public void Update(GameTime gameTime)
        {
            if (flag == null && GameObject.relativeObject.position.X + GameObject.relativeObject.drawPosition.X > block[1].position.X + (Tile.Size * Block.Width / 2))
            {
                block[0] = block[1];
                geiserList[0] = geiserList[1];
                geiserList[1] = new List<Geiser>();
                CreateNextBlock();
            }
            foreach (Geiser g in geiserList[0]) g.Update(gameTime);
            foreach (Geiser g in geiserList[1]) g.Update(gameTime);
            if (flag != null)
                flag.Update(gameTime);
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            Vector2 relPos = GameObject.relativeObject.position - GameObject.relativeObject.drawPosition;

            block[0].Draw(spriteBatch, 0, relPos);
            block[0].Draw(spriteBatch, 1, relPos);
            block[0].DrawUnderground(spriteBatch, relPos);
            foreach (Geiser g in geiserList[0]) g.Draw(spriteBatch);

            block[1].Draw(spriteBatch, 0, relPos);
            block[1].Draw(spriteBatch, 1, relPos);
            block[1].DrawUnderground(spriteBatch, relPos);
            foreach (Geiser g in geiserList[1]) g.Draw(spriteBatch);

            if (flag != null)
                flag.Draw(spriteBatch);
        }

        public void DrawForeground(SpriteBatch spriteBatch)
        {
            Vector2 relPos = GameObject.relativeObject.position - GameObject.relativeObject.drawPosition;
            block[0].Draw(spriteBatch, 2, relPos);
            block[1].Draw(spriteBatch, 2, relPos);
        }

        private void CreateNextBlock()
        {
            string filename = "";
            if (ps.level < 5)
            {
                string[] blockNameList = Directory.GetFiles("Content\\Blocks\\" + ps.level.ToString(), "*.block");
                while ((filename = blockNameList[Rand.Next(blockNameList.Length)]) == block[0].filePath) ; // faz com que o novo bloco1 não seja igual ao anterior
            }
            else filename = "Content\\Blocks\\b.block";

            int i = 0;
            for (i = 0; i < Block.Height; ++i)
                if (block[0].map[1][i][Block.Width - 1] != 0) break;
            block[1] = new Block(block[0].position + new Vector2(Block.Width * Tile.Size, (i - Block.Height + 1) * Tile.Size), filename);

            for (i = 0; i < Block.Height; ++i)
                if (block[1].map[1][i][0] != 0) break;
            block[1].position.Y -= (i - Block.Height + 1) * Tile.Size;

            // pega os tiles especiais do novo bloco
            CheckSpecialTiles(1);
        }

        public void CheckSpecialTiles(int n)
        {
            for (int i = 0; i < Block.Height; ++i)
                for (int j = 0; j < Block.Width; ++j)
                {
                    for (int k = 0; k < 3; ++k)
                    {
                        if (block[n].map[k][i][j] == geiserCode) { geiserList[n].Add(new Geiser(ps, block[n].GetPos(new Point(j, i)))); break; }
                        if (block[n].map[k][i][j] == flagCode && flag == null) { flag = new Flag(ps, block[n].GetPos(new Point(j, i))); break; }
                    }
                }
        }

        // Collision

        public float CollV(EngineObject obj, bool isUp)
        {
            return 0;
        }

        public float CollisionV(EngineObject obj, bool isUp)
        {
            return isUp ? Math.Max(block[0].CollisionUp(obj, obj == ps.c), block[1].CollisionUp(obj, obj == ps.c)) :
                          Math.Min(block[0].CollisionDown(obj, obj == ps.c), block[1].CollisionDown(obj, obj == ps.c));
        }

        public float CollisionH(EngineObject obj, bool isLeft)
        {
            return isLeft ? Math.Max(block[0].CollisionLeft(obj, obj == ps.c), block[1].CollisionLeft(obj, obj == ps.c)) : 
                            Math.Min(block[0].CollisionRight(obj, obj == ps.c), block[1].CollisionRight(obj, obj == ps.c));
        }


    }
}